/*
 When new serial data arrives, this sketch adds it to a String.
 When a newline is received, the loop prints the string and 
 clears it.
 
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 */
 
 // include the library code:
#include <LiquidCrystal.h>
#include <LM335A.h>
#include <Timer.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
LM335A insideTemp(0);
LM335A outsideTemp(1);
int lightPin01 = A2;
int lightPin02 = A3;
String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete
int reedSwitch = 8;
const int ledPin =  13;
Timer timer;
int ledState = LOW;
// sensor values
int reedSensorValue;
long LGT01;
long LGT02;
float TMP01;
float TMP02;
// previous reading from the reed switch
int lastReedSensorValue = LOW;
// counter and sum of sensor values
long counter = 0;
long sumLGT01 = 0;
float sumTMP01 = 0;
long sumLGT02 = 0;
float sumTMP02 = 0;
// the following variables are long because the time is measured in miliseconds
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 500;    // the debounce time; increase if the output flickers


void setup() {
  // initialize serial:
  Serial.begin(9600);
  lcd.begin(16, 2);
  // reserve 200 bytes for the inputString:
  inputString.reserve(200);
  pinMode(reedSwitch, INPUT);
  pinMode(ledPin, OUTPUT);
  int sendSensorValuesEvent = timer.every(60000, sendSensorValuesToServer);
  int printOnLcdEvent = timer.every(1000, printOnLcd);
}

void loop() {
  timer.update();
  insideTemp.ReadTemp();
  outsideTemp.ReadTemp();
  // set LED ON or OFF depending on string received from server 
  if (stringComplete) {
    encodeReceivedCommand();
    // clear the string:
    inputString = "";
    stringComplete = false;
  }
  // read sensor values
  TMP01 = insideTemp.Celsius();
  TMP02 = outsideTemp.Celsius();
  int reedSensorReading = digitalRead(reedSwitch);
  LGT01 = analogRead(lightPin01);
  LGT02 = analogRead(lightPin02);
  //Serial.println(temp);
  digitalWrite(ledPin, ledState);
  // If reed switch changed state:
  if (reedSensorReading != lastReedSensorValue) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }
  // whatever the reading is at, it's been there for longer
  // than the debounce delay, so take it as the actual current state:
  if ((millis() - lastDebounceTime) > debounceDelay) {
	// send command to server only if status is changed
    if (reedSensorReading != reedSensorValue) {
      String reedStr = "ARD#MGN#MGN01#" + String(reedSensorReading) + "\n";
      Serial.println(reedStr);
    }
    reedSensorValue = reedSensorReading;
  }
    // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastReedSensorValue = reedSensorReading;

  // counter and sum of sensor values
  counter = counter + 1;
  sumTMP01 = sumTMP01 + TMP01;
  sumTMP02 = sumTMP02 + TMP02;
  sumLGT01 = sumLGT01 + LGT01;
  sumLGT02 = sumLGT02 + LGT02;
  
}

/*
  SerialEvent occurs whenever a new data comes in the
 hardware serial RX.  This routine is run between each
 time loop() runs, so using delay inside loop can delay
 response.  Multiple bytes of data may be available.
 */
void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read(); 
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    }
  }
}

// Send sensor values to server over serial connection
void sendSensorValuesToServer()
{
  char tempValueAsString[20];
  //convert temp value to string
  String(dtostrf(sumTMP01/counter, 5, 2, tempValueAsString));
  String str = String("ARD#TMP#TMP01#") + tempValueAsString + String("\n");
  Serial.println(str);
  String(dtostrf(sumTMP02/counter, 5, 2, tempValueAsString));
  str = String("ARD#TMP#TMP02#") + tempValueAsString + String("\n");
  Serial.println(str);
  str = "ARD#LGT#LGT01#" + String(sumLGT01/counter) + "\n";
  Serial.println(str);
  str = "ARD#LGT#LGT02#" + String(sumLGT02/counter) + "\n";
  Serial.println(str);
  counter = 0;
  sumTMP01 = 0;
  sumTMP02 = 0;
  sumLGT01 = 0;
  sumLGT02 = 0;
}

void printOnLcd()
{
  // set output of LCD
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("TMP01: ");
  lcd.print(TMP01);
  lcd.setCursor(0, 1);
  lcd.print("TMP02: ");
  lcd.print(TMP02);
}

// encode received command from serial input
void encodeReceivedCommand()
{
  if (inputString.equals("SRV#LED#LED01#1\n")) {
    ledState = HIGH;
  }
  else if (inputString.equals("SRV#LED#LED01#0\n")) {
    ledState = LOW;
  }
}